package com.geovis.emergency.spd.controller.mobile;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.geovis.common.auth.util.AuthUtil;
import com.geovis.common.core.api.Result;
import com.geovis.common.core.controller.BaseController;
import com.geovis.emergency.spd.biz.basic.service.IBasicPunchRuleService;
import com.geovis.emergency.spd.biz.pc.service.IPcPunchRecordService;
import com.geovis.emergency.spd.biz.pc.service.IPcPunchService;
import com.geovis.emergency.spd.entity.basic.entity.BasicPunchRule;
import com.geovis.emergency.spd.entity.basic.entity.PcPunch;
import com.geovis.emergency.spd.entity.basic.entity.PcPunchRecord;
import com.geovis.emergency.spd.entity.mobile.pojo.vo.*;
import com.geovis.emergency.spd.entity.pc.pojo.enums.PunchStatusEnum;
import com.geovis.emergency.spd.entity.pc.pojo.enums.StatusEnum;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author ：linwl
 * @date ：Created in 2022/6/17 17:14
 * @description：移动端-应级源指挥模块-签到相关接口
 * @version: v1
 */

@RestController
@RequestMapping("/mobile/pcCheckIn")
@RequiredArgsConstructor
@Api(value = "移动端-应急预案指挥模块-打卡相关接口", tags = "移动端-应急预案指挥模块-打卡相关接口")
@Slf4j
public class PcCheckInMobileController extends BaseController<IPcPunchService> {

    private final IBasicPunchRuleService basicPunchRuleService;
    private final IPcPunchRecordService pcPunchRecordService;

    @ApiOperationSupport(order = 1)
    @ApiOperation(value = "获取打卡配置", notes = "传演练id(pcDrillId)")
    @GetMapping("getConfig/{pcDrillId}")
    public Result<SignMobileConfigVO> getConfig(@ApiParam("演练id") @PathVariable String pcDrillId) {
        String userId = AuthUtil.getCurrentUserId();
        if (userId == null) {
            return Result.failed("获取不到登录信息,请重新登录");
        }
//        BasicPunchRule punchRule = basicPunchRuleService.getByPcDrillId(userId, pcDrillId);
        BasicPunchRule punchRule = basicPunchRuleService.getById("1");
        if (punchRule == null) {
            return Result.failed("您无需打卡，如有疑问请联系管理员配置打卡规则");
        }
        Date now = new Date();
        SignMobileConfigVO vo = new SignMobileConfigVO();
        vo.setAddress(punchRule.getAddress());
        vo.setLatAndLng(StrUtil.format("{},{}", punchRule.getLongitude(), punchRule.getLatitude()));
        vo.setScope(punchRule.getRangeRadius());
        vo.setSignInTime(punchRule.getSignInTime());
        vo.setSignOutTime(punchRule.getSignOutTime());
        vo.setBusinessTrip(punchRule.getBusinessTrip());
        PcPunch pcPunch = baseService.selectUserPunch(userId, pcDrillId, now);
        if (pcPunch == null) {
            vo.setHasSignIn(false);
            vo.setHasSignOut(false);
            return Result.ok(vo);
        }
        vo.setHasSignIn(StatusEnum.TRUE.getCode().equals(pcPunch.getSignInStatus()));
        vo.setHasSignOut(StatusEnum.TRUE.getCode().equals(pcPunch.getSignOutStatus()));
        if(StatusEnum.TRUE.getCode().equals(pcPunch.getSignOutStatus())) {
            PcPunchRecord pcPunchRecord = pcPunchRecordService.selectByPunchIdAndTime(pcPunch.getId(), "2");
            vo.setLogSignOutTime(DateUtil.format(pcPunchRecord.getPunchTime(), "HH:mm"));
            Date punchTime = Date.from(pcPunchRecord.getPunchTime().atZone(ZoneId.systemDefault()).toInstant());
            DateTime signOutTime = DateUtil.parseTimeToday(punchRule.getSignOutTime());
            if (punchTime.before(signOutTime)) {
                vo.setLogSignOutMsg("早退");
            } else {
                vo.setLogSignOutMsg("已签退");
            }
        }
        if(StatusEnum.TRUE.getCode().equals(pcPunch.getSignInStatus())){
            PcPunchRecord pcPunchRecord =  pcPunchRecordService.selectByPunchIdAndTime(pcPunch.getId(),"1");
            vo.setLogSignInTime(DateUtil.format(pcPunchRecord.getPunchTime(),"HH:mm"));
            Date punchTime = Date.from(pcPunchRecord.getPunchTime().atZone(ZoneId.systemDefault()).toInstant());
            DateTime signInTime = DateUtil.parseTimeToday(punchRule.getSignInTime());
            if(punchTime.after(signInTime)){
                vo.setLogSignInMsg("迟到");
            }else{
                vo.setLogSignInMsg("已打卡");
            }
        }
        return Result.ok(vo);
    }

    /**
     * 签到打卡逻辑：
     *   签到：判断是否已经签到，若无，判断是否在签到时间内，若是，进行签到打卡
     *   签退：判断是否已经签退，若无，判断是否在签退时间内，若是，进行签退打卡
     * @param vo
     * @return
     */
    @ApiOperationSupport(order = 2)
    @ApiOperation(value = "签到", notes = "传演练id(pcDrillId)")
    @PostMapping("sign")
    @Transactional(rollbackFor = Exception.class)
    public Result<Void> signIn(@RequestBody @Valid MobileSignVO vo){
        //封装基础数据
        String userId = AuthUtil.getCurrentUserId();
        if (userId == null) {
            return Result.failed("获取不到登录信息,请重新登录");
        }
        BasicPunchRule punchRule = basicPunchRuleService.getById("1");
        if(punchRule==null){
            return Result.failed("您无需打卡，如有疑问请联系管理员配置打卡规则");
        }
        Date now = new Date();
        Date signInDate = DateUtil.parseTimeToday(punchRule.getSignInTime());
        Date signOutDate = DateUtil.parseTimeToday(punchRule.getSignOutTime());

        //更新以及持久化打卡信息
        PcPunch pcPunch = baseService.selectUserPunch(userId, vo.getPcDrillId(), now);
        if(pcPunch==null){
            pcPunch = new PcPunch();
            pcPunch.setPcDrillId(vo.getPcDrillId());
            pcPunch.setBasicPunchId(punchRule.getId());
            pcPunch.setPersonId(userId);
            pcPunch.setPunchDate(LocalDateTime.now());
            pcPunch.setWorkingHours(new BigDecimal("0"));
            pcPunch.setStatus(StatusEnum.TRUE.getCode());
            pcPunch.setSignInStatus(StatusEnum.FALSE.getCode());
            pcPunch.setSignOutStatus(StatusEnum.FALSE.getCode());
        }
        //一天只能打2次卡
        if (pcPunch.getSignInStatus().equals(StatusEnum.TRUE.getCode()) && pcPunch.getSignOutStatus().equals(StatusEnum.TRUE.getCode()))
        {
            return Result.failed("您已经达到每天打卡最大次数！");
        }

        PcPunchRecord pcPunchRecord = new PcPunchRecord();
        if(StatusEnum.FALSE.getCode().equals(pcPunch.getSignInStatus())){
            if(signInDate.after(now)){
                pcPunch.setStatus(PunchStatusEnum.BE_LATE.getCode());
            }
            pcPunch.setSignInStatus(StatusEnum.TRUE.getCode());
            pcPunchRecord.setType("1");
        }else if(StatusEnum.FALSE.getCode().equals(pcPunch.getSignOutStatus())){
            if(signOutDate.before(now)){
                pcPunch.setStatus(PunchStatusEnum.LEAVE_EARLY.getCode());
            }
            pcPunch.setSignOutStatus(StatusEnum.TRUE.getCode());
            pcPunchRecord.setType("2");
        }
        //持久化打卡信息
        pcPunch.setType(vo.getType());
        baseService.saveOrUpdate(pcPunch);

        //持久化打卡记录

        pcPunchRecord.setPcDrillId(vo.getPcDrillId());
        pcPunchRecord.setPcPunchId(pcPunch.getId());
        pcPunchRecord.setBasicPunchId(pcPunch.getBasicPunchId());

        pcPunchRecord.setPersonId(userId);
        pcPunchRecord.setLongitude(vo.getLongitude());
        pcPunchRecord.setLatitude(vo.getLatitude());
        pcPunchRecord.setAddress(vo.getAddress());
        pcPunchRecord.setPunchTime(LocalDateTime.now());
        pcPunchRecordService.save(pcPunchRecord);
        return Result.ok();
    }

    @ApiOperationSupport(order = 4)
    @ApiOperation(value = "打卡统计", notes = "传演练id(pcDrillId)和起始和结束时间(YYYY-MM-dd)")
    @GetMapping("statistics")
    public Result<List<MobileLabelVO>> statistics(String pcDrillId,String startDate,String endDate){
        String userId = AuthUtil.getCurrentUserId();
        return Result.ok(baseService.statisticsTotal(userId,pcDrillId,startDate,endDate));
    }

    @ApiOperationSupport(order = 4)
    @ApiOperation(value = "每日打卡记录", notes = "传演练id(pcDrillId)和时间(YYYY-MM)")
    @GetMapping("logList/{pcDrillId}/{date}")
    public Result<List<MobileSignInStatisticsVO>> logList(@ApiParam("推演id") @PathVariable("pcDrillId") String pcDrillId,
                                                             @ApiParam("日期(格式:YYYY-MM-dd)")@PathVariable("date") String date){
        String userId = AuthUtil.getCurrentUserId();
        List<MobileSignInStatisticsVO> voList = baseService.mobileStatistics(userId,pcDrillId,date);
        return Result.ok(voList);
    }

    @ApiOperationSupport(order = 4)
    @ApiOperation(value = "按天统计打卡记录(考勤日历)", notes = "传演练id(pcDrillId)和时间(YYYY-MM)")
    @GetMapping("statByDays")
    public Result<List<MobileSignStatisticsByDaysVO>> statByDays(String pcDrillId,String startDate,String endDate){
        String userId = AuthUtil.getCurrentUserId();
        List<MobileSignStatisticsByDaysVO> daysVOS = baseService.mobileSignStatisticsByDaysVO(userId,pcDrillId,startDate,endDate);
        return Result.ok(daysVOS);
    }

    @ApiOperationSupport(order = 4)
    @ApiOperation(value = "记录详情", notes = "传id")
    @GetMapping("detail/{id}")
    public Result<List<MobileSignDetailVO>> detail(@PathVariable String id){
        PcPunch pcPunch = baseService.getById(id);
        BasicPunchRule basicPunchRule = basicPunchRuleService.getById(pcPunch.getBasicPunchId());
        List<MobileSignDetailVO> vos = new ArrayList<>();

        MobileSignDetailVO signIn = new MobileSignDetailVO();
        signIn.setName("上班");
        signIn.setTime(basicPunchRule.getSignInTime());
        //已签到
        if(StatusEnum.TRUE.getCode().equals(pcPunch.getSignInStatus())){
            PcPunchRecord pcPunchRecord =  pcPunchRecordService.selectByPunchIdAndTime(pcPunch.getId(),"1");
            signIn.setSignTime(DateUtil.format(pcPunchRecord.getPunchTime(),"HH:mm"));
            Date punchTime = Date.from(pcPunchRecord.getPunchTime().atZone(ZoneId.systemDefault()).toInstant());
            DateTime signInTime = DateUtil.parseTimeToday(basicPunchRule.getSignInTime());
            if(punchTime.after(signInTime)){
                signIn.setNormal(StatusEnum.FALSE.getCode());
                signIn.setDescribe("迟到");
            }else{
                signIn.setNormal(StatusEnum.TRUE.getCode());
                signIn.setDescribe("已打卡");
            }
        }else{
            signIn.setNormal(StatusEnum.FALSE.getCode());
            signIn.setDescribe("未打卡");
        }
        MobileSignDetailVO signOut = new MobileSignDetailVO();
        signOut.setName("上班");
        signOut.setTime(basicPunchRule.getSignInTime());
        //已签到
        if(StatusEnum.TRUE.getCode().equals(pcPunch.getSignOutStatus())){
            PcPunchRecord pcPunchRecord = pcPunchRecordService.selectByPunchIdAndTime(pcPunch.getId(),"2");
            signOut.setSignTime(DateUtil.format(pcPunchRecord.getPunchTime(),"HH:mm"));
            Date punchTime = Date.from(pcPunchRecord.getPunchTime().atZone(ZoneId.systemDefault()).toInstant());
            DateTime signOutTime = DateUtil.parseTimeToday(basicPunchRule.getSignOutTime());
            if(punchTime.before(signOutTime)){
                signOut.setNormal(StatusEnum.FALSE.getCode());
                signOut.setDescribe("早退");
            }else{
                signOut.setNormal(StatusEnum.TRUE.getCode());
                signOut.setDescribe("已签退");
            }
        }else{
            signOut.setNormal(StatusEnum.FALSE.getCode());
            signOut.setDescribe("未打卡");
        }
        vos.add(signIn);
        vos.add(signOut);
        return Result.ok(vos);
    }

}
